package cn.edu.jxau.core.service;


import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;



import cn.edu.jxau.core.controller.ServiceResultConfig;
import cn.edu.jxau.core.exception.ServiceException;
import cn.edu.jxau.core.util.DateUtils;
import cn.edu.jxau.core.util.StringUtil;
import cn.edu.jxau.framework.dao.core.Session;
import cn.edu.jxau.framework.dao.core.sqlSessionFactory;

/**
 * 系统维护的业务类
 *@author 作者 :gong
 *@version 创建时间：2017年8月23日 下午3:13:25
 */
@SuppressWarnings("serial")
public class SystemMaintenanceService extends ServiceSupport{
	
	//mysql的bin路径
	private static String binPath = "D:\\Dev_Tool\\MySQL Server\\bin";
	//备份文件夹路径,注意加尾部的斜杠
	//private static String backupFloderPath = "/classes/sql/backupTablesAndDates/";
	private static String backupFloderPath = "/";
	//private static String backupFloderPath = "D:\\backupFloder\\";
	//备份数据库名
	private static String dataName = "spectrum";
	
	public SystemMaintenanceService(){
		super();
	}
	
	public SystemMaintenanceService(String view, Map<String, Object[]> params, Map<String, Object> data) throws ServiceException {
		/**
         * view service.xml中的name和视图对应
         * params request入口的参数数组
         * data 返回给Servlet的出口参数
         */
		super(view, params, data);
		execute(view, params, data); // 执行业务
        
	}

	
	
	/**
	 * 添加维护信息
	 * @return
	 */
	@SuppressWarnings("unused")
	private void insertMaintenance(Map<String, Object[]> params, Map<String, Object> data){
		Map<String, Object> param = new HashMap<String, Object>(); //用来封装传递给数据库的参数
        List<HashMap<String, Object>> datas = new ArrayList();  // 用来接收数据库返回回来的 
        
        //获取当前系统的时间
        String maintenanceTime =  DateUtils.getNowDateTime();
        
        //获取维护信息类型 0/1 0表示恢复，1是备份
        String maintenanceType = getParamStringValue(params, "maintenanceType", 0);
        
        String fileAddress = null;
        //根据维护类型来判断是否需要得到维护信息的id,执行恢复,参数1是id，参数2是备份时间
        if("1".equals(maintenanceType)){
        	String maintenanceId = getParamStringValue(params, "maintenanceId", 0);
        	System.out.println("maintenanceId is：" +maintenanceId);
        	
        	fileAddress = getMaintenance(maintenanceId);       	
        	recoverDatabase(fileAddress, maintenanceTime);
    	}
        //根据请求备份数据库,参数是维护时间
        else if("0".equals(maintenanceType)){
        	fileAddress = backupDatabase();
        }
        //处理非法请求
        else{
        	
        }
       
        //获取维护信息名称
        String maintenanceName = getParamStringValue(params, "maintenanceName", 0);
        //如果维护信息名为空，自动分配维护名
        if(StringUtil.isBlank(maintenanceName)){
        	if("1".equals(maintenanceType)){
        		maintenanceName = "恢复数据";        		
        	}
        	
        	if("0".equals(maintenanceType)){
        		maintenanceName = "备份数据库";      		
        	}
        }
      
        //获取维护信息内容
        String maintenanceContent = getParamStringValue(params, "maintenanceContent", 0);
        //获取维护信息描述
        String maintenanceDescribe = getParamStringValue(params, "maintenanceDescribe", 0);
        
        
        
        //将需要得参数放在param中
        param.put("maintenanceId", null);
        param.put("maintenanceName", maintenanceName);
        param.put("maintenanceType", maintenanceType);
        param.put("maintenanceContent", maintenanceContent);
        param.put("maintenanceDescribe", maintenanceDescribe);
        param.put("fileAddress", fileAddress);
        param.put("maintenanceTime", maintenanceTime);
        System.out.println();
        //插入数据库
        try {
            Session session = sqlSessionFactory.getInstance().getSession();
            session.execute("insertMaintenance", param, datas);
            // 成功返回success   
            data.put("result", ServiceResultConfig.SUCCESS);           
            //释放会话
            session.releaseConnection();
        } catch (Exception e) {
        	//失败返回failed
        	data.put("result", ServiceResultConfig.FAILED);
        }
        
	}
	
	/**
	 * 获得所有的备份/恢复信息
	 * @param params
	 * @return
	 */
	@SuppressWarnings({ "unchecked" })
	private void listAllMaintenance(Map<String, String[]> params, Map<String, Object> data){
		Map<String, Object> param = new HashMap<String, Object>(); //用来封装传递给数据库的参数
        List<HashMap<String, Object>> datas = new ArrayList();  // 用来接收数据库返回回来的 	
        
        //通过数据库获得所有信息
        try {
        	
            Session session = sqlSessionFactory.getInstance().getSession();         
            session.execute("listAllMaintenance", param, datas);
            
        	// 成功返回success
        	data.put("result", ServiceResultConfig.SUCCESS);  
            /*for(HashMap<String, Object> test: datas){               	
            	for (Entry<String, Object> entry : test.entrySet()) {
            		   System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
            	}
            }*/
        	data.put("maintenances", datas);
           
            //释放会话
            session.releaseConnection();
        } catch (Exception e) {
        	System.out.println("error");
        }
        
	}
	
	/**
	 * 获得详细的系统维护信息
	 * @param params
	 * @param data
	 * @return
	 */
	private String getMaintenance(String maintenanceId){
		Map<String, Object> param = new HashMap<String, Object>(); //用来封装传递给数据库的参数
        List<HashMap<String, Object>> datas = new ArrayList();  // 用来接收数据库返回回来的 
        param.put("maintenanceId", maintenanceId);
        String fileAddress = null;
        //通过数据库获得所有信息
        try {
            Session session = sqlSessionFactory.getInstance().getSession();  
            System.out.println("set");
            session.execute("getMaintenance", param, datas);
            System.out.println("get");
            
        	// 成功返回success
        	/*System.out.println("success");
           
            for(HashMap<String, Object> test: datas){               	
            	for (Entry<String, Object> entry : test.entrySet()) {
            		if(entry.getKey().equals("fileAddress"))
            			fileAddress = (String) entry.getValue();
            		System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
            	}
             } */
                        
            //释放会话
            session.releaseConnection();
        } catch (Exception e) {
        	System.out.println("error");
        }
		return fileAddress;
	}
	
	/**
	 * 通过id获得Maintenance
	 * @param id 维护id
	 */
	private String getFileAddressById(String id){
		return id;
		
	}
	
	
	/**
	 * 备份数据库
	 * @param maintenanceTime 备份数据库的时间
	 * @return
	 */
	private String backupDatabase(){
		//通过类拿到绝对路径
		String path = getClass().getResource("").getFile().toString();
		path = path.substring(1, path.length() - 25) + "sql/backupTablesAndDates/";
		try {
            Runtime rt = Runtime.getRuntime();
            // 调用 调用mysql的安装目录的命令
            Process child = rt
                    .exec(binPath + "\\mysqldump -hlocalhost -uroot -proot " + dataName);
            // 设置导出编码为utf-8。这里必须是utf-8
            // 把进程执行中的控制台输出信息写入.sql文件，即生成了备份文件。注：如果不对控制台信息进行读出，则会导致进程堵塞无法运行
            InputStream in = child.getInputStream();// 控制台的输出信息作为输入流
 
            // 设置输出流编码为utf-8。这里必须是utf-8，否则从流中读入的是乱码
            InputStreamReader backupTofile = new InputStreamReader(in, "utf-8");
            	
            String inStr;
            StringBuffer sb = new StringBuffer("");
            String outStr;
            // 组合控制台输出信息字符串
            BufferedReader br = new BufferedReader(backupTofile);
            while ((inStr = br.readLine()) != null) {
                sb.append(inStr + "\r\n");
            }
            outStr = sb.toString();
            
            //备份文件地址
            String backupfileAddress = path +"spectrum" + DateUtils.getNowDate() + ".sql";
            System.out.println(backupfileAddress);
            
            // 要用来做导入用的sql目标文件：
            FileOutputStream fout = new FileOutputStream(backupfileAddress);
            OutputStreamWriter writer = new OutputStreamWriter(fout, "utf-8");
            writer.write(outStr);
            writer.flush();
            in.close();
            backupTofile.close();
            br.close();
            writer.close();
            fout.close();
            return backupfileAddress;
        } 
		catch (Exception e) {
           return "error";
        }
	}
	
	/**
	 * 恢复数据库
	 * @param maintanceId 恢复数据库的文件对象
	 * @param maintenanceTime 恢复数据库的时间
	 */
	private void recoverDatabase(String filePath, String maintenanceTime){
		 try {
			 	System.out.println(filePath);
	            Runtime runtime = Runtime.getRuntime();
	            /*Process process = runtime
	                    .exec(binPath + "\\mysql.exe -hlocalhost -uroot -proot --default-character-set=utf8 "
	                            + dataName);*/
	            Process process = runtime
	                    .exec("mysql.exe -hlocalhost -uroot -proot --default-character-set=utf8 "
	                            + dataName);
	            OutputStream outputStream = process.getOutputStream();
	            BufferedReader br = new BufferedReader(new InputStreamReader(
	                    new FileInputStream(filePath), "utf-8"));
	            String str = null;
	            StringBuffer sb = new StringBuffer();
	            while ((str = br.readLine()) != null) {
	                sb.append(str + "\r\n");
	            }
	            str = sb.toString();
	            
	            OutputStreamWriter writer = new OutputStreamWriter(outputStream,
	                    "utf-8");
	            writer.write(str);
	            writer.flush();
	            outputStream.close();
	            br.close();
	            writer.close();
	        } catch (UnsupportedEncodingException e) {
	            e.printStackTrace();
	        } catch (FileNotFoundException e) {
	            e.printStackTrace();
	        } catch (IOException e) {
	            e.printStackTrace();
	        }
	}
}
